import axios from 'axios'
import { ElMessage } from 'element-plus'
import { CODE_STATE } from '@/api/code'
import { useRouter } from 'vue-router'
import { store } from '@/store/index'
import { getToken, setToken } from '@/plugins/cookie'
// import { HTTP_URL } from '@/api/base_url'
axios.defaults.timeout = 60000
axios.defaults.withCredentials = false
const router = useRouter()
const pending: any = [] // 声明一个数组用于存储每个请求的取消函数和axios标识
const removePending = (config: any) => {
  for (const p in pending) {
    if (pending[p].u === config.url + '&' + config.method + '&' + config.data) {
      // 当当前请求在数组中存在时执行函数体
      pending[p].f() // 执行取消操作
      pending.splice(p, 1)
    }
  }
}

// 声明一个对象用于存储请求个数
let needLoadingRequestCount = 0
function tryHideFullScreenLoading() {
  if (needLoadingRequestCount <= 0) return
  needLoadingRequestCount--
}

// HTTPrequest拦截
axios.interceptors.request.use(
  (config: any) => {
    const isToken = (config.headers || {}).isToken === false
    const token = getToken()
    if (token && !isToken) {
      config.headers['token'] = token // token
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 响应拦截
axios.interceptors.response.use(
  (res) => {
    tryHideFullScreenLoading()
    removePending(res.config) // 在一个axios响应后再执行一下取消操作，把已经完成的请求从pending中移除
    const code = res.data.status
    if (code) {
      switch (code) {
        // 正常交互
        case CODE_STATE.SUCCESS_OK:
          break
        case CODE_STATE.ACCESS_INVALID:
        case 10001:
          ElMessage({
            message: res.data.message,
            showClose: true,
            type: 'warning',
            duration: 2000,
          })
          //清除token
          setToken('')
          localStorage.removeItem('Token')
          window.localStorage.clear()
          store.commit('setUserInfo', {})
          // 跳转到登录页面
          window.location.href = '/#/login'
          break
        default:
          ElMessage({
            message: res.data.message,
            showClose: true,
            type: 'warning',
            duration: 2000,
          })
          break
      }
    }
    return res
  },
  (error) => {
    ElMessage.error(error)
    tryHideFullScreenLoading()
    if (error.message === 'Network Error') {
      ElMessage({
        message: '网络异常，请检查网络连接！',
        showClose: true,
        type: 'error',
        duration: 2000,
      })
    } else {
      // 获取状态码
      const { status } = error.response
      if (status === 401) {
        ElMessage({
          type: 'warning',
          message: '请重新登录',
        })
        // 清除token
        setToken('')
        localStorage.removeItem('Token')
        // 跳转到登录页面
        router.push({ path: '/login' })
      }
      if (status === 404) {
        router.push('/404')
      }
    }
    return Promise.reject(error)
  }
)

function removeEmptyField(obj: any) {
  let newObj: any = {}
  if (typeof obj === 'string') {
    obj = JSON.parse(obj)
  }
  if (obj instanceof Array) {
    newObj = []
  }
  if (obj instanceof Object) {
    for (const attr in obj) {
      // 属性值不为'',null,undefined才加入新对象里面(去掉'',null,undefined)
      // eslint-disable-next-line no-prototype-builtins
      if (
        // eslint-disable-next-line no-prototype-builtins
        obj.hasOwnProperty(attr) &&
        obj[attr] !== '' &&
        obj[attr] !== null &&
        obj[attr] !== undefined
      ) {
        if (obj[attr] instanceof Object) {
          // 空数组或空对象不加入新对象(去掉[],{})
          // if (JSON.stringify(obj[attr]) === '{}' || JSON.stringify(obj[attr]) === '[]') {
          //   continue
          // }
          // 属性值为对象,则递归执行去除方法
          newObj[attr] = removeEmptyField(obj[attr])
        } else if (
          typeof obj[attr] === 'string' &&
          ((obj[attr].indexOf('{') > -1 && obj[attr].indexOf('}') > -1) ||
            (obj[attr].indexOf('[') > -1 && obj[attr].indexOf(']') > -1))
        ) {
          // 属性值为JSON时
          try {
            const attrObj = JSON.parse(obj[attr])
            if (attrObj instanceof Object) {
              newObj[attr] = removeEmptyField(attrObj)
            }
          } catch (e) {
            newObj[attr] = obj[attr]
          }
        } else {
          newObj[attr] = obj[attr]
        }
      }
    }
  }
  return newObj
}

export function Fecth(url: String, data: any) {
  data = removeEmptyField(data)
  return new Promise((resolve, reject) => {
    const datas: any = {
      url: url,
      data: data,

      transformRequest: [
        function (data: any) {
          data = JSON.stringify(data)
          return data
        },
      ],
      headers: {
        'Content-Type': 'application/json',
      },
      method: 'POST',
    }
    axios(datas)
      .then((response) => {
        if (response.status === CODE_STATE.SUCCESS_OK) {
          resolve(response.data)
        }
      })
      .catch((error) => {
        reject(error)
      })
  })
}

export function FecthExport(url: String, data: any) {
  data = removeEmptyField(data)
  return new Promise((resolve, reject) => {
    const datas: any = {
      url: url,
      data: data,

      transformRequest: [
        function (data: any) {
          data = JSON.stringify(data)
          return data
        },
      ],
      headers: {
        'Content-Type': 'application/json',
      },
      responseType: 'blob',
      method: 'POST',
    }
    axios(datas)
      .then((response) => {
         resolve(response.data)
      })
      .catch((error) => {
        reject(error)
      })
  })
}

export function FecthUpload(url: String, data: any) {
  return new Promise((resolve, reject) => {
    const datas: any = {
      url: url,
      data: data,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      method: 'POST',
    }
    axios(datas)
      .then((response) => {
         resolve(response.data)
      })
      .catch((error) => {
        reject(error)
      })
  })
}
